package com.hy.movie.service.impl;

import cn.hutool.json.JSON;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.hy.movie.common.CommonResult;
import com.hy.movie.common.RedisKey;
import com.hy.movie.dao.ConsumerDao;
import com.hy.movie.model.bo.LoginBo;
import com.hy.movie.model.entity.Consumer;
import com.hy.movie.model.entity.WxAuthEntity;
import com.hy.movie.service.WeChatService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class WeChatServiceImpl implements WeChatService {
    @Value("${wxmini.sessionHost}")
    private String sessionHost;
    @Value("${wxmini.appId}")
    private String appId;
    @Value("${wxmini.secret}")
    private String secret;
    @Value("${wxmini.grantType}")
    private String grantType;
    private static final Long EXPIRES = 86400L;
    private RestTemplate wxAuthRestTemplate = new RestTemplate();
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private ConsumerDao consumerDao;
    @Override
    public CommonResult weChatLogin(String code) {
        WxAuthEntity wxAuthEntity = getWxSession(code);

        String wxOpenId = wxAuthEntity.getOpenId();
        String wxSessionKey = wxAuthEntity.getSessionKey();
        Consumer consumer = new Consumer();
        consumer.setOpenId(wxOpenId);
        loginOrRegisterConsumer(consumer);

        Long expires = wxAuthEntity.getExpireIn();
        String thirdSession = create3rdSession(wxOpenId, wxSessionKey, expires);
        LoginBo loginBo = new LoginBo();
        loginBo.setToken(thirdSession);
            return CommonResult.SUCCESS(loginBo);
    }

    private WxAuthEntity getWxSession(String code) {
        log.info("login in code is ",code);
        String urlString = "?appid={appid}&secret={srcret}&js_code={code}&grant_type={grantType}";
        String response = wxAuthRestTemplate.getForObject(
                sessionHost + urlString, String.class,
                appId,
               secret,
                code,
                grantType);
        ObjectMapper objectMapper = new ObjectMapper();
        ObjectReader reader = objectMapper.readerFor(WxAuthEntity.class);
        WxAuthEntity res;
        try {
            res = reader.readValue(response);
        } catch (IOException e) {
            res = null;
            log.error("反序列化失败", e);
        }
        log.info(response);
        if (null == res) {
            throw new RuntimeException("调用微信接口失败");
        }
        if (res.getErrCode() != null) {
            throw new RuntimeException(res.getErrMsg());
        }
        res.setExpireIn(res.getExpireIn() != null ? res.getExpireIn() : EXPIRES);
        return res;
    }

    private String create3rdSession(String wxOpenId, String wxSessionKey, Long expires) {
        String thirdSessionKey = RandomStringUtils.randomAlphanumeric(64);
        StringBuffer sb = new StringBuffer();
        sb.append(wxSessionKey).append("#").append(wxOpenId);
        stringRedisTemplate.opsForValue().set(RedisKey.WX_SESSION_ID.replace("{sessionId}",thirdSessionKey), sb.toString(), expires, TimeUnit.SECONDS);
        return thirdSessionKey;
    }

    private void loginOrRegisterConsumer(Consumer consumer) {
        QueryWrapper<Consumer> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("open_id",consumer.getOpenId());
        Consumer consumer1 = consumerDao.selectOne(queryWrapper);
        if (null == consumer1) {
            consumerDao.insert(consumer);
        }
    }

}
